/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! CHECKER      Test arithmetic aot
//! RUN_PAOC     options: "--compiler-regex '_GLOBAL::test_(\\w+_[if](_[if]|)|toboolean|ld.*|string|.*compare.*)'"
//! check_aot = lambda do |op, intrinsic, form, inst|
//!     METHOD       "test_#{op.downcase}_#{form}"
//!     PASS_BEFORE  "InlineIntrinsics"
//!     INST         "Intrinsic.#{intrinsic}"
//!     INST_NOT     inst
//!     PASS_AFTER   "InlineIntrinsics"
//!     INST_NOT     "Intrinsic.#{intrinsic}"
//!     INST         inst
//! end
//! check_aot.call(:Add, 'Add2Dyn', 'i_i', "AddOverflowCheck")
//! check_aot.call(:Add, 'Add2Dyn', 'i_f', /f64 +Add /)
//! check_aot.call(:Add, 'Add2Dyn', 'f_i', /f64 +Add /)
//! check_aot.call(:Add, 'Add2Dyn', 'f_f', /f64 +Add /)
//! check_aot.call(:Sub, 'Sub2Dyn', 'i_i', "SubOverflowCheck")
//! check_aot.call(:Sub, 'Sub2Dyn', 'i_f', /f64 +Sub /)
//! check_aot.call(:Sub, 'Sub2Dyn', 'f_i', /f64 +Sub /)
//! check_aot.call(:Sub, 'Sub2Dyn', 'f_f', /f64 +Sub /)
//! check_aot.call(:And, 'And2Dyn', 'i_i', /i32 +And /)
//! check_aot.call(:And, 'And2Dyn', 'i_f', /i32 +And /)
//! check_aot.call(:And, 'And2Dyn', 'f_i', /i32 +And /)
//! check_aot.call(:And, 'And2Dyn', 'f_f', /i32 +And /)
//! check_aot.call(:Or, 'Or2Dyn', 'i_i', /i32 +Or /)
//! check_aot.call(:Or, 'Or2Dyn', 'i_f', /i32 +Or /)
//! check_aot.call(:Or, 'Or2Dyn', 'f_i', /i32 +Or /)
//! check_aot.call(:Or, 'Or2Dyn', 'f_f', /i32 +Or /)
//! check_aot.call(:Xor, 'Xor2Dyn', 'i_i', /i32 +Xor /)
//! check_aot.call(:Xor, 'Xor2Dyn', 'i_f', /i32 +Xor /)
//! check_aot.call(:Xor, 'Xor2Dyn', 'f_i', /i32 +Xor /)
//! check_aot.call(:Xor, 'Xor2Dyn', 'f_f', /i32 +Xor /)
//! check_aot.call(:Shl, 'Shl2Dyn', 'i_i', /i32 +Shl /)
//! check_aot.call(:Shl, 'Shl2Dyn', 'i_f', /i32 +Shl /)
//! check_aot.call(:Shl, 'Shl2Dyn', 'f_i', /i32 +Shl /)
//! check_aot.call(:Shl, 'Shl2Dyn', 'f_f', /i32 +Shl /)
//! check_aot.call(:Shr, 'Shr2Dyn', 'i_i', /i32 +AShr /)
//! check_aot.call(:Shr, 'Shr2Dyn', 'i_f', /i32 +AShr /)
//! check_aot.call(:Shr, 'Shr2Dyn', 'f_i', /i32 +AShr /)
//! check_aot.call(:Shr, 'Shr2Dyn', 'f_f', /i32 +AShr /)
//! check_aot.call(:Mul, 'Mul2Dyn', 'i_i', /f64 +Mul /)
//! check_aot.call(:Mul, 'Mul2Dyn', 'i_f', /f64 +Mul /)
//! check_aot.call(:Mul, 'Mul2Dyn', 'f_i', /f64 +Mul /)
//! check_aot.call(:Mul, 'Mul2Dyn', 'f_f', /f64 +Mul /)
//! check_aot.call(:Div, 'Div2Dyn', 'i_i', /f64 +Div /)
//! check_aot.call(:Div, 'Div2Dyn', 'i_f', /f64 +Div /)
//! check_aot.call(:Div, 'Div2Dyn', 'f_i', /f64 +Div /)
//! check_aot.call(:Div, 'Div2Dyn', 'f_f', /f64 +Div /)
//! check_aot.call(:Mod, 'Mod2Dyn', 'i_i', /u32 +Mod /)
//! check_aot.call(:Mod, 'Mod2Dyn', 'i_f', /f64 +Mod /)
//! check_aot.call(:Mod, 'Mod2Dyn', 'f_i', /f64 +Mod /)
//! check_aot.call(:Mod, 'Mod2Dyn', 'f_f', /f64 +Mod /)
//! check_aot.call(:Not, 'NotDyn', 'i', /i32 +Not/)
//! check_aot.call(:Not, 'NotDyn', 'f', /i32 +Not/)
//! check_aot.call(:Neg, 'NegDyn', 'i', /NegOverflowAndZeroCheck/)
//! check_aot.call(:Neg, 'NegDyn', 'f', /f64 +Neg/)
//! check_aot.call(:Inc, 'IncDyn', 'i', /AddOverflowCheck/)
//! check_aot.call(:Inc, 'IncDyn', 'f', /f64 +Add/)
//! check_aot.call(:Dec, 'DecDyn', 'i', /SubOverflowCheck/)
//! check_aot.call(:Dec, 'DecDyn', 'f', /f64 +Sub/)
//! check_aot.call(:Ldtrue, 'Ldtrue', '', /i64 +Constant +0x1/)
//! check_aot.call(:Ldfalse, 'Ldfalse', '', /i64 +Constant +0x0/)
//! check_aot.call(:Ldnull, 'Ldnull', '', /any +Constant +0x2/)
//! check_aot.call(:Ldundefined, 'Ldundefined', '', /any +Constant +0xa/)
//! check_aot.call(:Ldinfinity, 'Ldinfinity', '', /f64 +Constant +inf/)
//! check_aot.call(:Ldnan, 'Ldnan', '', /f64 +Constant +nan/)
//!
//! forms = [['i_i', 'i32'], ['i_f', 'f64'], ['f_i', 'f64'], ['f_f', 'f64']]
//! insts = [['eq', 'Eq'], ['ne', 'NotEq'], ['ge', 'GreaterEq'], ['le', 'LessEq'], ['gt', 'Greater'], ['lt', 'Less'], ['eq', 'StrictEq'], ['ne', 'StrictNotEq']]
//! forms.each do |form, type|
//!     METHOD       "test_cmp_#{form}"
//!     PASS_BEFORE  "InlineIntrinsics"
//!     insts.each do |op, intrinsic|
//!         INST         "Intrinsic.#{intrinsic}Dyn"
//!     end
//!     PASS_AFTER   "InlineIntrinsics"
//!     insts.each do |op, intrinsic|
//!         INST_NOT     "Intrinsic.#{intrinsic}Dyn"
//!         if (['ge', 'le', 'gt', 'lt'].include? op) && type == 'f64'
//!             new_op = 'Fcmp' + (op[0] == 'g' ? 'l' : 'g')
//!             INST_NEXT    new_op
//!             INST_NEXT    "Compare #{op.upcase} i32"
//!         else
//!             INST_NEXT    "Compare #{op.upcase} #{type}"
//!         end
//!     end
//! end
//!
//! METHOD       "test_toboolean"
//! PASS_BEFORE  "InlineIntrinsics"
//! INST_COUNT   "Intrinsic.Toboolean", 5
//! PASS_AFTER   "InlineIntrinsics"
//! INST_COUNT   "Intrinsic.Toboolean", 2
//!
//! METHOD       "test_string"
//! PASS_BEFORE  "InlineIntrinsics"
//! INST         "Intrinsic.EqDyn"
//! INST_NEXT    "Intrinsic.NotEqDyn"
//! INST_NEXT    "Intrinsic.StrictEqDyn"
//! INST_NEXT    "Intrinsic.StrictNotEqDyn"
//! PASS_AFTER   "InlineIntrinsics"
//! INST_NOT     /Intrinsic.*EqDyn/
//! INST_COUNT   "Intrinsic.EcmaStringEquals", 4
//!
//! METHOD       "test_strict_compare_diff_types"
//! PASS_BEFORE  "InlineIntrinsics"
//! INST_COUNT   "Intrinsic.StrictNotEqDyn", 4
//! INST_COUNT   "Intrinsic.StrictEqDyn", 2
//! INST_COUNT   "Compare", 7
//! PASS_AFTER   "InlineIntrinsics"
//! INST_NOT     /Intrinsic.*EqDyn/
//! INST_COUNT   "Compare", 9
//!
//! METHOD       "test_compare_diff_types"
//! PASS_BEFORE  "InlineIntrinsics"
//! INST_COUNT   "Intrinsic.EqDyn", 8
//! INST_COUNT   "Intrinsic.NotEqDyn", 3
//! INST_COUNT   "Compare", 11
//! PASS_AFTER   "InlineIntrinsics"
//! INST_COUNT   "Intrinsic.EqDyn", 1
//! INST_NOT     "Intrinsic.NotEqDyn"
//! INST_COUNT   "Compare", 13
//!
//! RUN options: "--interpreter-type irtoc", entry: "_GLOBAL::func_main_0", force_jit: false
//!
//! EVENT_NOT /Deoptimization.*/
//! [:add, :sub, :and, :or, :xor, :shl, :shr, :mul, :div, :mod, :cmp].each do |op|
//!     ['i_i', 'i_f', 'f_i', 'f_f'].each { |form|
//!         EVENT /AotEntrypointFound,_GLOBAL::func_test_#{op}_#{form}_\d+/
//!     }
//! end
//!
//! [:not, :neg, :inc, :dec].each do |op|
//!     EVENT /AotEntrypointFound,_GLOBAL::func_test_#{op}_i_\d+/
//!     EVENT /AotEntrypointFound,_GLOBAL::func_test_#{op}_f_\d+/
//! end
//! EVENT /AotEntrypointFound,_GLOBAL::func_test_toboolean_\d+/

//! CHECKER      Test arithmetics in interpreter
//! RUN          options: "--interpreter-type irtoc", entry: "_GLOBAL::func_main_0", force_jit: false
//! EVENT_NOT    /AotEntrypointFound.*/

//! CHECKER      Test mod instruction
//! RUN          options: "--no-async-jit --compiler-hotness-threshold=1 --compiler-regex _GLOBAL::test_mod_with_.*_int", entry: "_GLOBAL::func_main_0"
//! EVENT_NOT    /AotEntrypointFound.*/
//! METHOD       "test_mod_with_neg_int"
//! PASS_BEFORE  "InlineIntrinsics"
//! INST         "Intrinsic.Mod2Dyn"
//! PASS_AFTER   "InlineIntrinsics"
//! INST_NOT     /Intrinsic.*Mod2Dyn/
//! INST         "f64  Mod"
//! METHOD       "test_mod_with_pos_int"
//! PASS_BEFORE  "InlineIntrinsics"
//! INST         "Intrinsic.Mod2Dyn"
//! PASS_AFTER   "InlineIntrinsics"
//! INST_NOT     /Intrinsic.*Mod2Dyn/
//! INST         "NegativeCheck"
//! INST_NEXT    "NotPositiveCheck"
//! INST_NEXT    "u32  Mod"
//! EVENT        /Compilation,_GLOBAL::test_mod_with_pos_int,.*,COMPILED/
//! TRUE         EVENT_COUNT(/DeoptimizationReason,.*test_mod_with_pos_int.*NEGATIVE_CHECK.*/) == 2


function test_add_i_i() {
    let a = 1;
    let b = 2;
    return a + b;
}

function test_add_i_f() {
    let a = 3;
    let b = 4.1;
    return a + b;
}

function test_add_f_i() {
    let a = 5.2;
    let b = 6;
    return a + b;
}

function test_add_f_f() {
    let a = 7.3;
    let b = 8.4;
    return a + b;
}

function test_add() {
    let res = 0;
    res += test_add_i_i();
    res += test_add_i_f();
    res += test_add_f_i();
    res += test_add_f_f();
    if (res != 37) {
        throw "test_add is failed";
    }
}

function test_sub_i_i() {
    let a = 1;
    let b = 2;
    return b - a;
}

function test_sub_i_f() {
    let a = 3;
    let b = 4.1;
    return b - a;
}

function test_sub_f_i() {
    let a = 5.2;
    let b = 6;
    return b - a;
}

function test_sub_f_f() {
    let a = 7.3;
    let b = 8.4;
    return b - a;
}

function test_sub() {
    let res = 0;
    res += test_sub_i_i();
    res += test_sub_i_f();
    res += test_sub_f_i();
    res += test_sub_f_f();
    if (res != 4) {
        throw "test_sub is failed";
    }
}

function test_and_i_i() {
    let a = 3;
    let b = 2;
    return a & b;
}

function test_and_i_f() {
    let a = 3;
    let b = 5.1;
    return a & b;
}

function test_and_f_i() {
    let a = 5.2;
    let b = 6;
    return a & b;
}

function test_and_f_f() {
    let a = 7.3;
    let b = 9.4;
    return a & b;
}

function test_and() {
    let res = 0;
    res += test_and_i_i();
    res += test_and_i_f();
    res += test_and_f_i();
    res += test_and_f_f();
    if (res != 8) {
        throw "test_and is failed";
    }
}

function test_or_i_i() {
    let a = 2;
    let b = 4;
    return a | b; // 6
}

function test_or_i_f() {
    let a = 3;
    let b = 5.1;
    return a | b; // 7
}

function test_or_f_i() {
    let a = 5.2;
    let b = 6;
    return a | b; // 7
}

function test_or_f_f() {
    let a = 7.3;
    let b = 9.4;
    return a | b; // 15
}

function test_or() {
    let res = 0;
    res += test_or_i_i();
    res += test_or_i_f();
    res += test_or_f_i();
    res += test_or_f_f();
    if (res != 35) {
        throw "test_or is failed";
    }
}

function test_xor_i_i() {
    let a = 1;
    let b = 4;
    return a ^ b; // 5
}

function test_xor_i_f() {
    let a = 3;
    let b = 5.1;
    return a ^ b; // 6
}

function test_xor_f_i() {
    let a = 5.2;
    let b = 6;
    return a ^ b; // 3
}

function test_xor_f_f() {
    let a = 7.3;
    let b = 9.4;
    return a ^ b; // 14
}

function test_xor() {
    let res = 0;
    res += test_xor_i_i();
    res += test_xor_i_f();
    res += test_xor_f_i();
    res += test_xor_f_f();
    if (res != 28) {
        throw "test_xor is failed";
    }
}

function test_shl_i_i() {
    let a = 1;
    let b = 2;
    return a << b; // 4
}

function test_shl_i_f() {
    let a = 1;
    let b = 2.7;
    return a << b; // 4
}

function test_shl_f_i() {
    let a = 3.2;
    let b = 2;
    return a << b; // 12
}

function test_shl_f_f() {
    let a = 3.2;
    let b = 4.4;
    return a << b; // 48
}

function test_shl() {
    let res = 0;
    res += test_shl_i_i();
    res += test_shl_i_f();
    res += test_shl_f_i();
    res += test_shl_f_f();
    if (res != 68) {
        throw "test_shl is failed";
    }
}

function test_shr_i_i() {
    let a = 4;
    let b = 1;
    return a >> b; // 2
}

function test_shr_i_f() {
    let a = 6;
    let b = 2.7;
    return a >> b; // 1
}

function test_shr_f_i() {
    let a = 7.2;
    let b = 2;
    return a >> b; // 1
}

function test_shr_f_f() {
    let a = 12.2;
    let b = 2.4;
    return a >> b; // 3
}

function test_shr() {
    let res = 0;
    res += test_shr_i_i();
    res += test_shr_i_f();
    res += test_shr_f_i();
    res += test_shr_f_f();
    if (res != 7) {
        throw "test_shr is failed";
    }
}

function test_mul_i_i() {
    let a = 2;
    let b = 4;
    return a * b; // 8
}

function test_mul_i_f() {
    let a = 2;
    let b = 2.7;
    return a * b; // 5.4
}

function test_mul_f_i() {
    let a = 3.2;
    let b = 2;
    return a * b; // 6.4
}

function test_mul_f_f() {
    let a = 3.2;
    let b = 4.4;
    return a * b; // 14.08
}

function test_mul() {
    let res = 0;
    res += test_mul_i_i();
    res += test_mul_i_f();
    res += test_mul_f_i();
    res += test_mul_f_f();
    if (!(res >= 33.7 && res <= 33.9)) {
        throw "test_mul is failed";
    }
}

function test_div_i_i() {
    let a = 4;
    let b = 2;
    return a / b; // 2
}

function test_div_i_f() {
    let a = 5;
    let b = 2.5;
    return a / b; // 2
}

function test_div_f_i() {
    let a = 4.8;
    let b = 2;
    return a / b; // 2.4
}

function test_div_f_f() {
    let a = 4.4;
    let b = 2.2;
    return a / b; // 2
}

function test_div() {
    let res = 0;
    res += test_div_i_i();
    res += test_div_i_f();
    res += test_div_f_i();
    res += test_div_f_f();
    if (res != 8.4) {
        throw "test_div is failed";
    }
}

function test_mod_i_i() {
    let a = 4;
    let b = 3;
    return a % b; // 1
}

function test_mod_i_f() {
    let a = 10;
    let b = 3.4;
    return a % b; // 3.2
}

function test_mod_f_i() {
    let a = 6.5;
    let b = 3;
    return a % b; // 0.5
}

function test_mod_f_f() {
    let a = 5.4;
    let b = 2.2;
    return a % b; // 1
}

function test_mod() {
    let res = 0;
    res += test_mod_i_i();
    res += test_mod_i_f();
    res += test_mod_f_i();
    res += test_mod_f_f();
    if (res != 5.7) {
        throw "test_mod is failed";
    }
}

function test_not_i() {
    let a = 1;
    return ~a; // -2
}

function test_not_f() {
    let a = 3.5;
    return ~a; // -4
}

function test_not() {
    let res = 0;
    res += test_not_i();
    res += test_not_f();
    if (res != -6) {
        throw "test_not is failed";
    }
}

function test_neg_i() {
    let a = 1;
    return -a; // -1
}

function test_neg_f() {
    let a = -3.5;
    return -a; // 3.5
}

function test_neg_i_overflow() {
    let a = -2147483648;
    return -a; // 2147483648
}

function test_neg_i_zero() {
    let a = 0;
    return 1/(-a); // -Infinity
}

function test_neg() {
    let res = 0;
    res += test_neg_i();
    res += test_neg_f();
    res += test_neg_i_overflow();
    if (res != 2147483650.5) {
        throw "test_neg is failed";
    }
    if (test_neg_i_zero() != -Infinity) {
        throw "test_neg is failed";
    }
}

function test_inc_i() {
    let a = 1;
    return ++a;
}

function test_inc_f() {
    let a = -3.5;
    return ++a;
}

function test_inc() {
    let res = 0;
    res += test_inc_i();
    res += test_inc_f();
    if (res != -0.5) {
        throw "test_inc is failed";
    }
}

function test_dec_i() {
    let a = 10;
    return --a;
}

function test_dec_f() {
    let a = 13.5;
    return --a;
}

function test_dec() {
    let res = 0;
    res += test_dec_i();
    res += test_dec_f();
    if (res != 21.5) {
        throw "test_dec is failed";
    }
}

function test_cmp_i_i() {
    let a = 1;
    let b = 2;
    let res = 0;
    if (a == b) res += 1;
    if (a != b) res += 2;
    if (a >= b) res += 3;
    if (a <= b) res += 4;
    if (a > b) res += 5;
    if (a < b) res += 6;
    if (a === b) res += 7;
    if (a !== b) res += 8;
    return res;  // 20
}

function test_cmp_i_f() {
    let a = 3;
    let b = 2.5;
    let res = 0;
    if (a == b) res += 11;
    if (a != b) res += 12;
    if (a >= b) res += 13;
    if (a <= b) res += 14;
    if (a > b) res += 15;
    if (a < b) res += 16;
    if (a === b) res += 17;
    if (a !== b) res += 18;
    // comparisons below are false
    if (a <= NaN) res += 19;
    if (a >= NaN) res += 20;
    if (a < NaN) res += 21;
    if (a > NaN) res += 22;
    return res;  // 58
}

function test_cmp_f_i() {
    let a = -5.2;
    let b = 2;
    let res = 0;
    if (a == b) res += 21;
    if (a != b) res += 22;
    if (a >= b) res += 23;
    if (a <= b) res += 24;
    if (a > b) res += 25;
    if (a < b) res += 26;
    if (a === b) res += 27;
    if (a !== b) res += 28;
    return res;  // 100
}

function test_cmp_f_f() {
    let a = -1.3;
    let b = 2.5;
    let res = 0;
    if (a == b) res += 31;
    if (a != b) res += 32;
    if (a >= b) res += 33;
    if (a <= b) res += 34;
    if (a > b) res += 35;
    if (a < b) res += 36;
    if (a === b) res += 37;
    if (a !== b) res += 38;
    if (NaN == NaN) res += 39; // false
    if (NaN != NaN) res += 40; // true
    return res;  // 180
}

function test_cmp() {
    let res = 0;
    res += test_cmp_i_i();
    res += test_cmp_i_f();
    res += test_cmp_f_i();
    res += test_cmp_f_f();
    if (res != 358) {
        throw "test_cmp is failed";
    }
}

function test_toboolean() {
    let res = 0;
    if (2) res += 1;
    if (2.5) res += 2;
    if ('test') res += 3;
    if (0) res += 4;
    if ('') res += 6;
    if (res != 6) {
        throw "test_toboolean is failed";
    }
}

function test_ldtrue() {
    return true;
}

function test_ldfalse() {
    return false;
}

function test_ldnull() {
    return null;
}

function test_ldundefined() {
    return undefined;
}

function test_ldinfinity() {
    return Infinity;
}

function test_ldnan() {
    return NaN;
}

// For correct check we do not need to compile this method.
function NO_COMPILE_test_ldconst() {
    let res = 0;
    if (test_ldtrue() == true) res += 1;
    if (test_ldfalse() == false) res += 2;
    if (test_ldnull() == null) res += 3;
    if (test_ldundefined() == undefined) res += 4;
    if (test_ldinfinity() == Infinity) res += 5;
    if (isNaN(test_ldnan())) res += 6;
    if (res != 21) {
        throw "NO_COMPILE_test_ldconst is failed";
    }
}

function test_string() {
    let a = "abcde";
    let b = "abcdf";
    let res = 0;
    if (a == b) res += 1;
    if (a != b) res += 2;
    if (a === b) res += 4;
    if (a !== b) res += 8;
    if (res != 10) {
        throw "test_string is failed"
    }
}

// Only two new Compare instructions should be created after inline_intrinsics,
// other comparisons should be replaced with true/false based on input types
function test_strict_compare_diff_types() {
    let a = "abcde";
    let b = 1.5;
    let res = 0;
    if (a !== b) res += 1;
    if (a !== null) res += 2;
    if (false !== null) res += 3;
    if (a === undefined) res += 7;
    if (b !== true) res += 8;
    if (b === 0) res += 9; // Compare EQ after inline_intrinsics
    if (res != 14) { // Compare NE after inline_intrinsics
        throw "test_strict_compare_diff_types is failed"
    }
}

// Only one new Compare instruction should be created after inline_intrinsics,
// other comparisons should be replaced with true/false or not inlined
function test_compare_diff_types() {
    let a = "1";
    let b = 1.5;
    let c = 1;
    let res = 0;
    if (null == null) res += 1; // true
    if (undefined == undefined) res += 2; // true
    if (null == undefined) res += 3; // true
    if (a == undefined) res += 7; // false
    if (undefined == b) res += 8; // false
    if (a == c) res += 9; // true, leave as intrinsic
    if (null != b) res += 10; // true
    if (null == c) res += 11; // false
    if (b == c) res += 12; // false, create Compare EQ
    if (undefined != null) res += 13; // false
    if (res != 25) { // Compare NE after inline_intrinsics
        throw "test_compare_diff_types is failed: " + res
    }
}

function test_mod_with_neg_int(a, b) {
    return a % b;
}

function test_mod_with_pos_int(a, b) {
    return (a % b) + 1;
}

test_add();
test_sub();
test_and();
test_or();
test_xor();
test_shl();
test_shr();
test_mul();
test_div();
test_mod();
test_not();
test_neg();
test_inc();
test_dec();
test_cmp();
test_toboolean();
NO_COMPILE_test_ldconst();
test_string();
test_strict_compare_diff_types();
test_compare_diff_types();

test_mod_with_neg_int(-3, 4);
test_mod_with_neg_int(-3, 4);
test_mod_with_pos_int(3, 4);
test_mod_with_pos_int(3, 4);
test_mod_with_pos_int(3, 0);
test_mod_with_pos_int(0, 3);
test_mod_with_pos_int(-1, 3);
